// ValidationAspects
// Written by Mike Saunders
// Released under Microsoft Public License (Ms-PL)
using System;
using NUnit.Framework;
using ValidationAspects;
using ValidationAspects.Sdk;

namespace TestValidationAspects
{
	[TestFixture]
	public class TestEmit
	{
		[SetUp]
		public void SetUp()
		{
			Emit<string>.Clear();
			Emit<Func<string, string>>.Clear();
			Emit<IMyEmit>.Clear();
		}

		[Test]
		public void Test_Emit_for_string_type_for_registered_funcs()
		{
			MockFactory factory = new MockFactory {StringData = "data"};

			Emit<string>.For<MockFactory>(f => "emit [" + f.StringData + "]");
			string emitString = Emit<string>.From(factory);

			Assert.AreEqual("emit [data]", emitString);
		}

		[Test]
		public void Test_Emit_for_Func_type_for_registered_funcs()
		{
			MockFactory factory = new MockFactory {StringData = "data"};

			Emit<Func<string, string>>.For<MockFactory>(f => i => f.StringData + i);
			Func<string, string> emitFunc = Emit<Func<string, string>>.From(factory);

			Assert.AreEqual("data and input", emitFunc(" and input"));
		}

		[Test]
		public void Test_Emit_for_interface_type_for_registered_funcs()
		{
			MockFactory factory = new MockFactory {StringData = "data"};

			Emit<IMyEmit>.For<MockFactory>(f => new MyEmit {Data = "data"});
			IMyEmit myEmit = Emit<IMyEmit>.From(factory);

			Assert.AreEqual("emitting from MyEmit [data]", myEmit.DoIt());
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Test_For_throws_for_null_emit_func()
		{
			Emit<string>.For<MockFactory>(null);
		}

		[Test]
		[ExpectedException(typeof(ArgumentNullException))]
		public void Test_From_throws_for_null_factory()
		{
			Emit<string>.From(null);
		}

		[Test]
		public void Test_From_returns_null_if_no_emit_func_is_registered_to_the_factory()
		{
			Assert.IsNull(Emit<string>.From(new MockFactory()));
		}

		[Test]
		public void Test_Clear()
		{
			MockFactory factory = new MockFactory();

			Emit<string>.For<MockFactory>(f => "emit");
			Assert.IsNotNull(Emit<string>.From(factory));

			Emit<string>.Clear();

			Assert.IsNull(Emit<string>.From(factory));
		}

		#region Mocks
		public class MockFactory : IValidatorFactory
		{
			public string StringData { get; set; }

			#region Implementation of IValidatorFactory
			public IValidator<T> Create<T>()
			{
				throw new NotImplementedException();
			}
			#endregion
		}

		public interface IMyEmit
		{
			string DoIt();
		}

		public class MyEmit : IMyEmit
		{
			public string Data { get; set; }

			#region Implementation of IEmit
			public string DoIt()
			{
				return string.Format("emitting from MyEmit [{0}]", Data);
			}
			#endregion
		}
		#endregion
	}
}